﻿#include "GAF_Package.h"
#include "GAF_Define.h"
#include "GAF_Platform.h"

namespace GAF
{
	Table<Package*> Package::PackageTable;

	Package* Package::GetDefaultPackage(const _STRING strPathName)
	{
		Package* _pPackage = NULL;
		_pPackage = PackageTable.Get(strPathName);

		if(_pPackage == NULL)
		{
			GAF_CHECK_R(strPathName != "", NULL);

			_STRING _strKind = "";
			_pPackage = GAF_pTHEAPP->CreateDefaultPackage(_strKind);

			if(_pPackage == NULL)
			{
				_pPackage = GAF_NEW(Package);
				_strKind = GAF_PACKAGE_DISK;
			}

			if(!_pPackage->Load(strPathName, _strKind))
			{
				GAF_ERROR("Load \"%s\" Package Error!", strPathName.c_str());
				return NULL;
			}

			PackageTable.Put(strPathName, _pPackage);
		}

		return _pPackage;
	}

	bool Package::DestroyOne(_STRING strPathName)
	{
		Package* _pPackage = PackageTable.Get(strPathName);

		if(_pPackage == NULL)
			return false;

		if(!_pPackage->Release())
			return false;

		PackageTable.Remove(strPathName);
		GAF_DELETE(_pPackage);
		return true;
	}

	bool Package::DestroyAll()
	{
		int nCount = PackageTable.GetCount();

		if(nCount > 0)
		{
			Package** ppPackages = GAF_NEW_ARY(Package*, nCount);

			PackageTable.Destroy(ppPackages);

			for(int i = 0; i < nCount; i++)
			{
				ppPackages[i]->Release();
				GAF_DELETE(ppPackages[i]);
			}
			GAF_DELETE_ARY(ppPackages);
		}

		return true;
	}



	Package::Package() :
		m_strPath(""),
		m_strKind(""),
		m_nResCount(-1)
	{

	}

	Package::~Package()
	{

	}

	bool Package::Load(_STRING strPathName, _STRING strKind)
	{
		GAF_CHECK_R(strPathName != "", false);

		m_strPath = strPathName;
		m_strKind = strKind;

		if(m_strKind != GAF_PACKAGE_DISK)
		{
			_STRING strName = m_strPath + "." + m_strKind;
			if(OnLoad(strName) == true)
				return true;
		}

		_STRING _strPathFiles = m_strPath;
		_strPathFiles += "/*.*";

		// 获取资源文件夹文件数
		m_nResCount = 0;

		// 检查磁盘目录
		_FS_DIR _dir;
		_FS_DATA _data;
		_FS_OPEN(_strPathFiles.c_str(), _dir, _data);

		if(_dir == _FS_DIR_ERROR)
		{
			GAF_ERROR("Load \"%s\" Disk Pack Is No Find!", m_strPath.c_str());
			return false;
		}
		if(m_strKind != GAF_PACKAGE_DISK)
		{
			GAF_WARM("Load \"%s\" Package Turn To Disk Path!", m_strPath.c_str());
		}
		m_strKind = GAF_PACKAGE_DISK;

		do 
		{
			if(_FS_DATA_ISKIND(_data, _FS_KIND_FILE))
				m_nResCount++;
		}while(_FS_READ(_dir, _data) != _FS_DIR_ERROR);
		_FS_CLOSE(_dir);

		return true;
	}

	ImageHandle Package::GetImageHandle(
		const _STRING strImageName,
		UINT& _OUT nWidth,
		UINT& _OUT nHeight,
		ImageInfo& _OUT ii
		)
	{
		ImageHandle _pOImage = NULL;

		_pOImage = m_tabImageHandles.Get(strImageName);

		if(_pOImage != NULL)
		{
			GAF_pTHEPLATFORM->GetImageInfo(_pOImage, nWidth, nHeight, ii);
			return _pOImage;
		}

#ifdef GAF_RES_DISK_FIRST
		_STRING _strName = m_strPath + "/" + strImageName;
		_pOImage = GAF_pTHEPLATFORM->NewImage(_strName, nWidth, nHeight, ii);
		if(_pOImage == NULL)
#endif
		{
#ifndef GAF_RES_DISK_FIRST
			if(m_strKind == GAF_PACKAGE_DISK)
			{
				_STRING _strPathName = m_strPath + "/" + strImageName;
				_pOImage = BASE(Package*) OnLoadImageHandle(_strPathName, nWidth, nHeight, ii);
			}
			else
#endif
			{
				_pOImage = OnLoadImageHandle(strImageName, nWidth, nHeight, ii);
			}
		}

		if(_pOImage != NULL)
		{
			m_tabImageHandles.Put(strImageName, _pOImage);
		}

		return _pOImage;
	}

	Image* Package::GetImage(const _STRING strImageName)
	{
		UINT _nWidth, _nHeight;
		ImageInfo _ii;

		ImageHandle _hImage = GetImageHandle(strImageName, _nWidth, _nHeight, _ii);

		if(_hImage == NULL)
			return NULL;

		Image* _pImage = Image::Create(_hImage, _nWidth, _nHeight, _ii);

		return _pImage;
	}

	bool Package::Release()
	{
		if(OnRelease() == false)
		{
			UINT _nCount = m_tabImageHandles.GetCount();
			if(_nCount > 0)
			{
				ImageHandle* _hImages = GAF_NEW_ARY(ImageHandle, _nCount);
				m_tabImageHandles.Clean(_hImages);

				for(UINT _i = 0; _i < _nCount; _i++)
				{
					OnDestroyImageHandle(_hImages[_i]);
				}

				GAF_DELETE_ARY(_hImages);
			}
		}
		return true;
	}

	_STRING Package::GetPathName()
	{
		return m_strPath;
	}

	_STRING Package::GetKind()
	{
		return m_strKind;
	}

	int Package::GetCount()
	{
		return m_nResCount;
	}

	ImageHandle Package::OnLoadImageHandle(
			const _STRING strImageName,
			UINT& _OUT nWidth,
			UINT& _OUT nHeight,
			ImageInfo& _OUT ii
		)
	{
		return GAF_pTHEPLATFORM->NewImage(strImageName, nWidth, nHeight, ii);
	}

	bool Package::OnDestroyImageHandle(ImageHandle hImage)
	{
		return GAF_pTHEPLATFORM->DeleteImage(hImage);
	}

}